home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 June / PCFJune.iso / mweb / MWEB Utils / ws295sdk.exe / Ws2sdkzp.exe / SAMPLES / LAYERED / DCATALOG.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-06  |  15.5 KB  |  579 lines

  1. /*++
  2.  
  3.      Copyright (c) 1996 Intel Corporation
  4.      Copyright (c) 1996 Microsoft Corporation
  5.      All Rights Reserved
  6.  
  7.      Permission is granted to use, copy and distribute this software and
  8.      its documentation for any purpose and without fee, provided, that
  9.      the above copyright notice and this statement appear in all copies.
  10.      Intel makes no representations about the suitability of this
  11.      software for any purpose.  This software is provided "AS IS."
  12.  
  13.      Intel specifically disclaims all warranties, express or implied,
  14.      and all liability, including consequential and other indirect
  15.      damages, for the use of this software, including liability for
  16.      infringement of any proprietary rights, and including the
  17.      warranties of merchantability and fitness for a particular purpose.
  18.      Intel does not assume any responsibility for any errors which may
  19.      appear in this software nor any responsibility to update it.
  20.  
  21.  
  22. Module Name:
  23.  
  24.     dcatalog.cpp
  25.  
  26. Abstract:
  27.  
  28.     This module contains the implementation of the dcatalog class. This class
  29.     maintains a catalog of installed WinSock2 service providers.
  30.  
  31. --*/
  32.  
  33. #include "precomp.h"
  34. #include "install.h"
  35.  
  36.  
  37. DCATALOG::DCATALOG()
  38. /*++
  39.  
  40. Routine Description:
  41.  
  42.     Constructor for the DCATALOG object. Set member variables to known
  43.     state. Initialization of the object is completed in Initialize().
  44.  
  45. Arguments:
  46.  
  47.     NONE.
  48.  
  49. Return Value:
  50.  
  51.     NONE.
  52.  
  53. --*/
  54. {
  55.  
  56.     m_num_items = 0;
  57.     m_local_item = NULL;
  58.  
  59.     // initialize the critical section object
  60.     InitializeCriticalSection( &m_catalog_lock );
  61.     InitializeListHead( &m_protocol_list );
  62. }
  63.  
  64. INT
  65. DCATALOG::Initialize(
  66.     )
  67. /*++
  68.  
  69. Routine Description:
  70.  
  71.     Initialization routine for the DCATALOG object. Completes the
  72.     initialization of the DCATALOG object.  This MUST be the first member
  73.     fuction called after a DCATALOG object is created.
  74.  
  75. Arguments:
  76.  
  77.     NONE.
  78.  
  79. Return Value:
  80.  
  81.     NO_ERROR if the fuction succeeds else a winsock2 error code.
  82.  
  83. --*/
  84. {
  85.     LPWSAPROTOCOL_INFOW   ProtocolInfoBuff = NULL;
  86.     DWORD                ProtocolInfoBuffSize = 0;
  87.     PPROTO_CATALOG_ITEM  CatalogItem;
  88.     INT                  ReturnCode;
  89.     INT                  ErrorCode;
  90.     INT                  EnumResult;
  91.     INT                  Index;
  92.  
  93.     // Call WSCEnumProtocols with a zero length buffer so we know what size to
  94.     // send in to get all the installed PROTOCOL_INFO structs.
  95.     WSCEnumProtocols(
  96.         NULL,                     // lpiProtocols
  97.         ProtocolInfoBuff,         // lpProtocolBuffer
  98.         & ProtocolInfoBuffSize,   // lpdwBufferLength
  99.         & ErrorCode);             // lpErrno
  100.  
  101.     ReturnCode = WSA_NOT_ENOUGH_MEMORY;
  102.     ProtocolInfoBuff = (LPWSAPROTOCOL_INFOW)new char[ProtocolInfoBuffSize];
  103.     if (ProtocolInfoBuff){
  104.         EnumResult = WSCEnumProtocols(
  105.             NULL,                     // lpiProtocols
  106.             ProtocolInfoBuff,         // lpProtocolBuffer
  107.             & ProtocolInfoBuffSize,   // lpdwBufferLength
  108.             & ErrorCode);
  109.  
  110.         ReturnCode = WSASYSNOTREADY;
  111.         if (EnumResult != SOCKET_ERROR){
  112.             for (Index=0; Index < EnumResult ; Index++){
  113.  
  114.                 //Create a new catalog item for the PROTOCOL_INFO struct.
  115.                 CatalogItem = new PROTO_CATALOG_ITEM;
  116.                 if (CatalogItem){
  117.  
  118.                     ReturnCode = CatalogItem->Initialize(
  119.                         &ProtocolInfoBuff[Index]);
  120.                     if (NO_ERROR == ReturnCode){
  121.  
  122.                         //Add the new catalog item to the catalog
  123.                         AcquireCatalogLock();
  124.                         AppendCatalogItem(
  125.                             CatalogItem);
  126.                         if (memcmp (&CatalogItem->GetProtocolInfo()->ProviderId,
  127.                                 &LayeredProviderGuid,
  128.                                 sizeof (GUID))==0)
  129.                             m_local_item = CatalogItem;
  130.                         ReleaseCatalogLock();
  131.                     } //if
  132.                     else{
  133.                         break;
  134.                     } //else
  135.                 } //if
  136.             } //for
  137.  
  138.             if ((NO_ERROR==ReturnCode)
  139.                     && (m_local_item==NULL))
  140.                 ReturnCode = WSASYSNOTREADY;
  141.         } //if
  142.         delete(ProtocolInfoBuff);
  143.     } //if
  144.     return(ReturnCode);
  145. }
  146.  
  147.  
  148.  
  149.  
  150. DCATALOG::~DCATALOG()
  151. /*++
  152.  
  153. Routine Description:
  154.  
  155.     This  function  destroys the catalog object.  It takes care of removing and
  156.     destroying  all  of  the  catalog  entries  in  the catalog.  This includes
  157.     destroying  all  of the DPROVIDER objects referenced by the catalog.  It is
  158.     the  caller's responsibility to make sure that the DPROVIDER objects are no
  159.     longer referenced.
  160.  
  161. Arguments:
  162.  
  163.     None
  164.  
  165. Return Value:
  166.  
  167.     None
  168.  
  169. Implementation Notes:
  170.  
  171.     for each catalog entry
  172.         remove the entry
  173.         get its DPROVIDER reference
  174.         if reference is non-null
  175.             Set providers for all entries with matching IDs null
  176.             destroy the DPROVIDER
  177.         endif
  178.         destroy the entry
  179.     end for
  180.     deallocate the list head
  181.     close the catalog registry mutex
  182. --*/
  183. {
  184.     PLIST_ENTRY  this_linkage;
  185.     PPROTO_CATALOG_ITEM  this_item;
  186.     PDPROVIDER  this_provider;
  187.  
  188.     DEBUGF(
  189.         DBG_TRACE,
  190.         ("Catalog destructor\n"));
  191.  
  192.     AcquireCatalogLock();
  193.  
  194.     while ((this_linkage = m_protocol_list.Flink) != & m_protocol_list) {
  195.         this_item = CONTAINING_RECORD(
  196.             this_linkage,        // address
  197.             PROTO_CATALOG_ITEM,  // type
  198.             m_CatalogLinkage     // field
  199.             );
  200.         RemoveCatalogItem(
  201.             this_item  // CatalogItem
  202.             );
  203.         this_provider = this_item->GetProvider();
  204.         if (this_provider)
  205.             delete this_provider;
  206.         delete this_item;
  207.     }  // while (get entry linkage)
  208.  
  209.     assert( m_num_items == 0 );
  210.  
  211.     ReleaseCatalogLock();
  212.     DeleteCriticalSection( &m_catalog_lock );
  213.  
  214. }  // ~DCATALOG
  215.  
  216.  
  217.  
  218.  
  219. VOID
  220. DCATALOG::EnumerateCatalogItems(
  221.     IN CATALOGITERATION  Iteration,
  222.     IN DWORD             PassBack
  223.     )
  224. /*++
  225.  
  226. Routine Description:
  227.  
  228.     This  procedure enumerates all of the DPROTO_CATALOG_ITEM structures in the
  229.     catalog  by  calling  the indicated iteration procedure once for each item.
  230.     The called procedure can stop the iteration early by returning FALSE.
  231.  
  232.     Note  that  the DPROVIDER associated with an enumerated DPROTO_CATALOG_ITEM
  233.     may  be  NULL.   To retrieve DPROTO_CATALOG_ITEM structure that has had its
  234.     DPROVIDER      loaded      and      initialized,      you      can      use
  235.     GetCatalogItemFromCatalogEntryId.
  236.  
  237. Arguments:
  238.  
  239.     Iteration - Supplies   a  reference  to  the  catalog  iteration  procedure
  240.                 supplied by the client.
  241.  
  242.     PassBack  - Supplies  a  value uninterpreted by this procedure.  This value
  243.                 is  passed  unmodified to the catalog iteration procedure.  The
  244.                 client can use this value to carry context between the original
  245.                 call site and the iteration procedure.
  246.  
  247. Return Value:
  248.  
  249.     None
  250. --*/
  251. {
  252.     PLIST_ENTRY         ListMember;
  253.     PPROTO_CATALOG_ITEM CatalogEntry;
  254.     BOOL                enumerate_more;
  255.  
  256.     assert(Iteration != NULL);
  257.  
  258.     enumerate_more = TRUE;
  259.  
  260.     AcquireCatalogLock();
  261.  
  262.     ListMember = m_protocol_list.Flink;
  263.  
  264.     while (enumerate_more && (ListMember != & m_protocol_list)) {
  265.         CatalogEntry = CONTAINING_RECORD(
  266.             ListMember,
  267.             PROTO_CATALOG_ITEM,
  268.             m_CatalogLinkage);
  269.         ListMember = ListMember->Flink;
  270.         enumerate_more = (* Iteration) (
  271.             PassBack,     // PassBack
  272.             CatalogEntry  // CatalogEntry
  273.             );
  274.     } //while
  275.  
  276.     ReleaseCatalogLock();
  277.  
  278. }  // EnumerateCatalogItems
  279.  
  280.  
  281.  
  282. INT
  283. DCATALOG::FindNextProviderInChain(
  284.         IN  LPWSAPROTOCOL_INFOW lpProtocolInfo,
  285.         OUT PDPROVIDER          *NextProvider,
  286.         OUT PPROTO_CATALOG_ITEM    *BaseProviderCatalogEntry
  287.     )
  288. /*++
  289.  
  290. Routine Description:
  291.  
  292.     This procedure finds and loads the provider below this
  293.     provider in the protocol chain.
  294.  
  295. Arguments:
  296.     lpLocalProtocolInfo - A pointer to the WSAPROTOCOL_INFO struct for the
  297.                           current protocol chain.
  298.  
  299.     NextProvider        - A pointer to DPROVIDER object pointer for the
  300.                           next provider in chain
  301.     BaseProviderCatalogEntry - If next provider is a base provider, this
  302.                           pointer will contain the next provider catalog
  303.                           entry
  304. Return Value:
  305.  
  306.     NO_ERROR if the next provider is located else a valid winsock2 error
  307.     code.
  308. --*/
  309. {
  310.  
  311.     PLIST_ENTRY         ListMember;
  312.     PPROTO_CATALOG_ITEM CatalogEntry;
  313.     PPROTO_CATALOG_ITEM NextProviderCatalogEntry;
  314.     DWORD                LocalCatalogEntryId;
  315.     DWORD               NextProviderCatalogEntryId;
  316.     INT                 Index;
  317.     INT                 ReturnCode =WSASYSNOTREADY;
  318.  
  319.     assert (NextProvider!=NULL);
  320.     
  321.     if (m_local_item==NULL)
  322.         return WSASYSNOTREADY;
  323.  
  324.     LocalCatalogEntryId = m_local_item->GetProtocolInfo()->dwCatalogEntryId;
  325.  
  326.     AcquireCatalogLock();
  327.  
  328.     // First try to see if we have processed this chain already and
  329.     // thus loaded the provider that follows us in it
  330.     ListMember = m_protocol_list.Flink;
  331.  
  332.     while (ListMember != & m_protocol_list) {
  333.  
  334.         CatalogEntry = CONTAINING_RECORD(
  335.             ListMember,
  336.             PROTO_CATALOG_ITEM,
  337.             m_CatalogLinkage);
  338.         ListMember = ListMember->Flink;
  339.         if (CatalogEntry->GetProtocolInfo()->dwCatalogEntryId ==
  340.                     lpProtocolInfo->dwCatalogEntryId) {
  341.             *NextProvider = CatalogEntry->GetProvider ();
  342.             if (*NextProvider!=NULL) {
  343.                  ReturnCode = NO_ERROR;
  344.             }
  345.             else {
  346.                 //
  347.                 // Get the next providers CatalogEntryId from the protocol chain
  348.                 //
  349.                 for (Index=0;
  350.                      Index < lpProtocolInfo->ProtocolChain.ChainLen;
  351.                      Index++){
  352.                     if ((LocalCatalogEntryId==
  353.                             lpProtocolInfo->ProtocolChain.ChainEntries[Index])
  354.                             && (lpProtocolInfo->ProtocolChain.ChainLen>Index+1)) {
  355.                         NextProviderCatalogEntryId =
  356.                             lpProtocolInfo->ProtocolChain.ChainEntries[Index+1];
  357.                         break;
  358.                     } //if
  359.                 } // for
  360.                 //
  361.                 // If we found ourselves before reaching the end of the chain,
  362.                 // go load the next guy in the chain
  363.                 //
  364.                 if (Index<lpProtocolInfo->ProtocolChain.ChainLen) {
  365.                     ReturnCode = GetCatalogItemFromCatalogEntryId (
  366.                             NextProviderCatalogEntryId,
  367.                             &NextProviderCatalogEntry);
  368.                     if (NO_ERROR==ReturnCode) {
  369.                         // Pass the chain protocol info if
  370.                         // the provider we are loading is not
  371.                         // the last in the chain (base provider)
  372.                         if (Index==lpProtocolInfo->ProtocolChain.ChainLen-1)
  373.                             ReturnCode = LoadProvider (
  374.                                 NextProviderCatalogEntry,
  375.                                     NextProviderCatalogEntry->GetProtocolInfo(),
  376.                                     NextProvider);
  377.                         else
  378.                             ReturnCode = LoadProvider (
  379.                                 NextProviderCatalogEntry,
  380.                                     lpProtocolInfo,
  381.                                     NextProvider);
  382.  
  383.                         // Cache provider if we succeded
  384.                         if (NO_ERROR==ReturnCode) {
  385.                             CatalogEntry->SetProvider (*NextProvider);
  386.                             CatalogEntry->SetProviderCatalogEntry (NextProviderCatalogEntry);
  387.                         }
  388.                     } //if
  389.                 }
  390.             }
  391.             if ((NO_ERROR==ReturnCode)
  392.                     && (CatalogEntry->GetProviderCatalogEntry()->GetProtocolInfo()->ProtocolChain.ChainLen==BASE_PROTOCOL))
  393.                 *BaseProviderCatalogEntry = CatalogEntry->GetProviderCatalogEntry();
  394.                 
  395.             break;
  396.         }
  397.     }
  398.  
  399.     ReleaseCatalogLock();
  400.     return(ReturnCode);
  401. }
  402.  
  403.  
  404.  
  405. INT
  406. DCATALOG::GetCatalogItemFromCatalogEntryId(
  407.     IN  DWORD                     CatalogEntryId,
  408.     OUT PPROTO_CATALOG_ITEM FAR * CatalogItem
  409.     )
  410. /*++
  411.  
  412. Routine Description:
  413.  
  414.     This  procedure  retrieves  a  reference  to a catalog item given a catalog
  415.     entry ID to search for.
  416.  
  417.  
  418. Arguments:
  419.  
  420.     CatalogEntryId  - Supplies The ID of a catalog entry to be searched for.
  421.  
  422.     CatalogItem     - Returns a reference to the catalog item with the matching
  423.                       catalog entry ID if it is found, otherwise returns NULL.
  424.  
  425. Return Value:
  426.  
  427.   The  function  returns  NO_ERROR  if  successful, otherwise it returns an
  428.   appropriate WinSock error code.
  429. --*/
  430. {
  431.     PLIST_ENTRY         ListMember;
  432.     INT                 ReturnCode=WSASYSNOTREADY;
  433.     PPROTO_CATALOG_ITEM CatalogEntry;
  434.  
  435.     assert(CatalogItem != NULL);
  436.  
  437.     // Prepare for early error return
  438.     * CatalogItem = NULL;
  439.  
  440.     AcquireCatalogLock();
  441.  
  442.     ListMember = m_protocol_list.Flink;
  443.  
  444.     while (ListMember != & m_protocol_list) {
  445.  
  446.         CatalogEntry = CONTAINING_RECORD(
  447.             ListMember,
  448.             PROTO_CATALOG_ITEM,
  449.             m_CatalogLinkage);
  450.         ListMember = ListMember->Flink;
  451.         if (CatalogEntry->GetProtocolInfo()->dwCatalogEntryId ==
  452.                 CatalogEntryId) {
  453.             * CatalogItem = CatalogEntry;
  454.             ReturnCode = NO_ERROR;
  455.             break;
  456.         } //if
  457.     } //while
  458.  
  459.     ReleaseCatalogLock();
  460.     return(ReturnCode);
  461. }  // GetCatalogItemFromCatalogEntryId
  462.  
  463.  
  464.  
  465. INT
  466. DCATALOG::LoadProvider(
  467.     IN PPROTO_CATALOG_ITEM CatalogEntry,
  468.     IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
  469.     OUT PDPROVIDER         *Provider
  470.     )
  471. /*++
  472.  
  473. Routine Description:
  474.  
  475.     Load   the   provider  described  by  CatalogEntry.
  476.  
  477. Arguments:
  478.  
  479.     CatalogEntry - Supplies  a reference to a protocol catalog entry describing
  480.                    the provider to load.
  481.  
  482.     lpProtocolInfo - Protocol info structure to pass to provider when
  483.                     loading it
  484.  
  485.     Provider     - Returns a reference to the newly loaded provider object.
  486.  
  487. Return Value:
  488.  
  489.     The  function  returns NO_ERROR if successful, otherwise it returns an
  490.     appropriate WinSock error code.
  491. --*/
  492. {
  493.     INT ReturnCode = WSA_NOT_ENOUGH_MEMORY;
  494.     PDPROVIDER LocalProvider;
  495.  
  496.     assert(CatalogEntry != NULL);
  497.     assert(Provider != NULL);
  498.  
  499.     *Provider = NULL;
  500.  
  501.     LocalProvider = new(DPROVIDER);
  502.     if (LocalProvider) {
  503.  
  504.         ReturnCode = LocalProvider->Initialize(
  505.             CatalogEntry->GetLibraryPath(),
  506.             lpProtocolInfo
  507.             );
  508.         if (NO_ERROR == ReturnCode) {
  509.             *Provider = LocalProvider;
  510.         } //if
  511.         else {
  512.             delete(LocalProvider);
  513.         } //else
  514.     } //if
  515.     return(ReturnCode);
  516. }  // LoadProvider
  517.  
  518.  
  519.  
  520. VOID
  521. DCATALOG::AppendCatalogItem(
  522.     IN  PPROTO_CATALOG_ITEM  CatalogItem
  523.     )
  524. /*++
  525.  
  526. Routine Description:
  527.  
  528.     This procedure appends a catalog item to the end of the (in-memory) catalog
  529.     object.   It becomes the last item in the catalog.
  530.  
  531. Arguments:
  532.  
  533.     CatalogItem - Supplies a reference to the catalog item to be added.
  534.  
  535. Return Value:
  536.  
  537.     None
  538. --*/
  539. {
  540.     assert(CatalogItem != NULL);
  541.  
  542.     InsertTailList(
  543.         & m_protocol_list,               // ListHead
  544.         & CatalogItem->m_CatalogLinkage  // Entry
  545.        );
  546.     m_num_items++;
  547. }  // AppendCatalogItem
  548.  
  549.  
  550.  
  551. VOID
  552. DCATALOG::RemoveCatalogItem(
  553.     IN  PPROTO_CATALOG_ITEM  CatalogItem
  554.     )
  555. /*++
  556.  
  557. Routine Description:
  558.  
  559.     This  procedure removes a catalog item from the (in-memory) catalog object.
  560.     The catalog information in the registry is NOT updated.
  561.  
  562. Arguments:
  563.  
  564.     CatalogItem - Supplies a reference to the catalog item to be removed.
  565.  
  566. Return Value:
  567.  
  568.     None
  569. --*/
  570. {
  571.     assert(CatalogItem != NULL);
  572.  
  573.     RemoveEntryList(
  574.         & CatalogItem->m_CatalogLinkage  // Entry
  575.         );
  576.     assert(m_num_items > 0);
  577.     m_num_items--;
  578. }  // RemoveCatalogItem
  579.